#######################################
# Required CMake version              #
#######################################
cmake_minimum_required( VERSION 3.3 )

#######################################
# Project name                        #
#######################################
project( OpENer LANGUAGES C VERSION 2.3 )

#######################################
# Project version                     #
#######################################

if( NOT DEFINED OpENer_Device_Config_Vendor_Id )
  set( OpENer_Device_Config_Vendor_Id 1 CACHE STRING "Device Vendor ID" )
endif()
if( NOT DEFINED OpENer_Device_Config_Device_Type )
  set( OpENer_Device_Config_Device_Type 12 CACHE STRING "Device Type ID" )
endif()
if( NOT DEFINED OpENer_Device_Config_Product_Code )
  set( OpENer_Device_Config_Product_Code 65001 CACHE STRING "Device Product Code" )
endif()
if( NOT DEFINED OpENer_Device_Config_Device_Name )
  set( OpENer_Device_Config_Device_Name "OpENer PC" CACHE STRING "Device Name" )
endif()

configure_file(  
	"${PROJECT_SOURCE_DIR}/src/ports/devicedata.h.in"
	"${PROJECT_BINARY_DIR}/src/ports/devicedata.h"
	)

find_path( OpENer_BUILDSUPPORT_DIR OpENer.cmake ${PROJECT_SOURCE_DIR}/buildsupport )
 
INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/OpENer.cmake )

option(OPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER "Shall produced data from OpENer also include a run idle header?" FALSE)
option(OPENER_CONSUMED_DATA_HAS_RUN_IDLE_HEADER "Will consumed data from OpENer also include a run idle header?" TRUE)

if(OPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER)
  add_definitions(-DOPENER_PRODUCED_DATA_HAS_RUN_IDLE_HEADER)
endif()

if(OPENER_CONSUMED_DATA_HAS_RUN_IDLE_HEADER)
  add_definitions(-DOPENER_CONSUMED_DATA_HAS_RUN_IDLE_HEADER)
endif()

option(OPENER_IS_DLR_DEVICE "Is OpENer built with support for a basic DLR device?" FALSE)
if (OPENER_IS_DLR_DEVICE)
  add_definitions(-DOPENER_IS_DLR_DEVICE)
endif()

# The number of bytes used for the buffer that will be used for generating any reply data of messages.
# There are two uses in OpENer:
#   1. Explicit messages will use this buffer to store the data generated by the request
#   2. I/O Connections will use this buffer for the produced data
set( OPENER_MESSAGE_DATA_REPLY_BUFFER "200" CACHE STRING "The number of bytes used for the reply message buffer")
add_definitions(-DOPENER_MESSAGE_DATA_REPLY_BUFFER=${OPENER_MESSAGE_DATA_REPLY_BUFFER} )

#######################################
# Platform switches                   #
#######################################
set( OpENer_KNOWN_PLATFORMS "POSIX" "WIN32" "MINGW")

set( OpENer_PLATFORM CACHE STRINGS "Platform OpENer will be built for" )
set_property(CACHE OpENer_PLATFORM PROPERTY STRINGS ${OpENer_KNOWN_PLATFORMS} )

#######################################
# Platform-dependent functions check  #
#######################################
INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/OpENer_function_checks.cmake )

#######################################
# OpENer 64-bit data types            #
#######################################
set( OpENer_64_BIT_DATA_TYPES_ENABLED CACHE BOOL "Enable 64-bit data type support" )
if( OpENer_64_BIT_DATA_TYPES_ENABLED )
  add_definitions( -DOPENER_SUPPORT_64BIT_DATATYPES )
endif( OpENer_64_BIT_DATA_TYPES_ENABLED )

#######################################
# OpENer tracer switches              #
#######################################
set( OpENer_TRACES OFF CACHE BOOL "Activate OpENer traces" )
if(OpENer_TRACES)
  createTraceLevelOptions()
endif(OpENer_TRACES)

#######################################
# OpENer library mode switch          #
#######################################
set( OPENER_BUILD_SHARED_LIBS OFF CACHE BOOL "Builds OpENer as separate lib and sample application" )

#######################################
# OpENer documentation target "doc"   #
#######################################

# check if Doxygen is installed
find_package(Doxygen)
if (DOXYGEN_FOUND)
    # set input and output files
    set(DOXYGEN_IN ${OpENer_SOURCE_DIR}/opener.doxyfile.in)
    set(DOXYGEN_OUT ${OpENer_BINARY_DIR}/opener.doxyfile)

    # exclude subdirectories of non active platforms depending on OpENer_PLATFORM
    set(OpENer_EXCLUDE_PATTERNS "")
    if (NOT (${OpENer_PLATFORM} STREQUAL "POSIX"))
        set(OpENer_EXCLUDE_PATTERNS "${OpENer_EXCLUDE_PATTERNS} */src/ports/POSIX/*")
    endif ()
    if (NOT (${OpENer_PLATFORM} STREQUAL "WIN32"))
        set(OpENer_EXCLUDE_PATTERNS "${OpENer_EXCLUDE_PATTERNS} */src/ports/WIN32/*")
    endif ()
    if (NOT (${OpENer_PLATFORM} STREQUAL "MINGW"))
        set(OpENer_EXCLUDE_PATTERNS "${OpENer_EXCLUDE_PATTERNS} */src/ports/MINGW/*")
    endif ()

    # request to configure the file
    configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)

    # note the option ALL which will build the docs always with the default target
    add_custom_target( doc # ALL
        COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
        WORKING_DIRECTORY ${OpENer_SOURCE_DIR}
        COMMENT "Generating API documentation with Doxygen"
        VERBATIM )
    message("-- Doxygen setup done")
else (DOXYGEN_FOUND)
  message("Doxygen needs to be installed to generate the Doxygen documentation")
endif (DOXYGEN_FOUND)


#######################################
# Test switch                         #
#######################################
set( OpENer_TESTS OFF CACHE BOOL "Enable tests to be built" )
if( OpENer_TESTS )
  enable_testing()
  enable_language( CXX )
  set( CPPUTEST_HOME "" CACHE PATH "Path to CppUTest directory" )
  INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/OpENer_Tests.cmake )
  INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/CodeCoverage.cmake )
  set(COVERAGE_LCOV_EXCLUDES 'tests/*' 'usr/*' 'ports/POSIX/sample_application/*')
  SETUP_TARGET_FOR_COVERAGE_LCOV(NAME ${PROJECT_NAME}_coverage EXECUTABLE OpENer_Tests DEPENDENCIES OpENer_Tests)
  add_test_includes()
  add_subdirectory( tests )
endif( OpENer_TESTS )

#######################################
# OpENer C flags                      #
#######################################
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall" )

####################################################
# Internal cache holding the available CIP objects #
####################################################
set( OpENer_ADD_CIP_OBJECTS "" CACHE INTERNAL STRING )
set( OpENer_ADD_CIP_OBJECTS_INCLUDES "" CACHE INTERNAL STRING )

#######################################
# Add custom CIP objects              #
#######################################
set( OpENer_CIP_OBJECTS_DIR ${PROJECT_SOURCE_DIR}/src/cip_objects )
include(${OpENer_BUILDSUPPORT_DIR}/OpENer_CIP_Object_generator.cmake)

#######################################
# Add subdirectories                  #
#######################################
add_subdirectory( src )
